source('../settings/settings.R')
source('commonFunctions.R')
drive1 <- read.csv('../data/processed/analysis/TT1_Drive_1_PP.csv')
drive2 <- read.csv('../data/processed/Analysis/TT1_Drive_2_PP.csv')
drive3 <- read.csv('../data/processed/Analysis/TT1_Drive_3_PP.csv')
drive4 <- read.csv('../data/processed/Analysis/TT1_Drive_4_PP.csv', stringsAsFactors = T)
set.seed(43)
combinedDf <- cbind(drive4,
drive1$MeanPP_Seg0,
drive2$MeanPP, drive3$MeanPP,
drive2$StdPP, drive3$StdPP,
drive2$MeanPP_SegMax, drive3$MeanPP_SegMax,
drive2$MeanPP_Seg0, drive3$MeanPP_Seg0,
drive2$StdPP_SegMax, drive3$StdPP_SegMax,
drive2$StdPP_Seg0, drive3$StdPP_Seg0
)
names(combinedDf) <- c(names(drive4),
"PP_Dev_1_Turning",
"PP_Dev_2", "PP_Dev_3",
"Std_PP_2", "Std_PP_3",
"PP_Dev_2_Straight", "PP_Dev_3_Straight",
"PP_Dev_2_Turning", "PP_Dev_3_Turning",
"Std_PP_2_Straight", "Std_PP_3_Straight",
"Std_PP_2_Turning", "Std_PP_3_Turning"
)
combinedDf$Subject <- paste0("#", str_pad(combinedDf$Subject, 2, pad="0"))
# combinedDf$PP_Dev_2_Turning <- ifelse(combinedDf$PP_Dev_2_Turning > 0, combinedDf$PP_Dev_2_Turning, combinedDf$PP_Dev_2_Straight)
combinedDf_NoStressor <- combinedDf[combinedDf$Activity == "NO",]
combinedDf_Cognitive <- combinedDf[combinedDf$Activity == "C",]
combinedDf_Motoric <- combinedDf[combinedDf$Activity == "M",]
combinedDf_NoStressor$Subject <- as.factor(combinedDf_NoStressor$Subject)
combinedDf_Cognitive$Subject <- as.factor(combinedDf_Cognitive$Subject)
combinedDf_Motoric$Subject <- as.factor(combinedDf_Motoric$Subject)
COLOR_NORMAL <- list(color='rgb(120,120,120)')
COLOR_COGNITIVE <- list(color='rgb(158,202,225)')
COLOR_MOTORIC <- list(color='rgb(58,200,225)')
COLOR_FAILURE_PRIOR <- list(color='rgb(158,202,225)')
COLOR_FAILURE <- list(color='red')
yAxis <- list(
title = 'Perinasal Perspiration (Log)',
range=c(-0.3, 0.5)
)
# Apply Otsu algorithm to select threshold
ppDev <- combinedDf$PP_Dev
ppDevArray <- matrix(ppDev ,nrow = 1,ncol = length(ppDev))
THRESHOLD_MILD = otsu(ppDevArray, range=c(min(ppDev), max(ppDev))) # Expected Threshold > 0.042
print(paste0('Threshold: ', THRESHOLD_MILD))
[1] "Threshold: 0.062365390625"
MARKER_LINE_MILD = list(color="blue")
MARKER_LINE_EXTREME = list(color="red")
fig_NoStressor <- plot_ly(combinedDf_NoStressor, x = ~Subject, y = ~PP_Dev_2_Straight, type = 'bar', name = 'Cognitive - Mean PP (Straight)', marker=COLOR_COGNITIVE) %>%
add_trace(y = ~PP_Dev_3_Straight, name = 'Motoric - Mean PP (Straight)', marker=COLOR_MOTORIC) %>%
add_trace(y = ~PP_Dev_2_Turning, name = 'Cognitive - Mean PP (Turning)', marker=COLOR_COGNITIVE) %>%
add_trace(y = ~PP_Dev_3_Turning, name = 'Motoric - Mean PP (Turning)', marker=COLOR_MOTORIC) %>%
add_trace(y = ~PP_Prior, name = 'Failure - Prior PP', marker=COLOR_FAILURE_PRIOR) %>%
add_trace(y = ~PP_Dev, name = 'Failure - PP Deviation', marker=COLOR_FAILURE) %>%
add_segments(x="#01", xend="#41", y = THRESHOLD_MILD, yend = THRESHOLD_MILD, name="Threshold: Mild Change of PP",
line=list(color="blue", dash = 'dot')) %>%
# add_segments(x="#01", xend="#41", y = THRESHOLD_EXTREME, yend = THRESHOLD_EXTREME, name="Threshold: Extreme Change of PP",
# line=list(color="darkred", dash = 'dot')) %>%
layout(yaxis = yAxis, barmode = 'group', title="No Stressor")
htmltools::tagList(fig_NoStressor)
A marker object has been specified, but markers is not in the mode
Adding markers to the mode...
A marker object has been specified, but markers is not in the mode
Adding markers to the mode...
fig_Cognitive <- plot_ly(combinedDf_Cognitive, x = ~Subject, y = ~PP_Dev_2_Straight, type = 'bar', name = 'Cognitive - Mean PP (Straight)', marker=COLOR_COGNITIVE) %>%
add_trace(y = ~PP_Dev_3_Straight, name = 'Motoric - Mean PP (Straight)', marker=COLOR_MOTORIC) %>%
add_trace(y = ~PP_Dev_2_Turning, name = 'Cognitive - Mean PP (Turning)', marker=COLOR_COGNITIVE) %>%
add_trace(y = ~PP_Dev_3_Turning, name = 'Motoric - Mean PP (Turning)', marker=COLOR_MOTORIC) %>%
add_trace(y = ~PP_Prior, name = 'Failure - Prior PP', marker=COLOR_FAILURE_PRIOR) %>%
add_trace(y = ~PP_Dev, name = 'Failure - PP Deviation', marker=COLOR_FAILURE) %>%
add_segments(x="#02", xend="#22", y = THRESHOLD_MILD, yend = THRESHOLD_MILD, name="Threshold: Mild Change of PP",
line=list(color="blue", dash = 'dot')) %>%
# add_segments(x="#02", xend="#22", y = THRESHOLD_EXTREME, yend = THRESHOLD_EXTREME, name="Threshold: Extreme Change of PP",
# line=list(color="darkred", dash = 'dot')) %>%
layout(yaxis = yAxis, barmode = 'group', title="Stressor = Cognitive")
htmltools::tagList(fig_Cognitive)
A marker object has been specified, but markers is not in the mode
Adding markers to the mode...
A marker object has been specified, but markers is not in the mode
Adding markers to the mode...
fig_Motoric <- plot_ly(combinedDf_Motoric, x = ~Subject, y = ~PP_Dev_2_Straight, type = 'bar', name = 'Arousal in Drive C - Straight segment', marker=COLOR_COGNITIVE, width=870) %>%
add_trace(y = ~PP_Dev_3_Straight, name = 'Arousal in Drive M - Straight segment', marker=COLOR_MOTORIC) %>%
add_trace(y = ~PP_Dev_2_Turning, name = 'Arousal in Drive C - Turning segment', marker=COLOR_COGNITIVE) %>%
add_trace(y = ~PP_Dev_3_Turning, name = 'Arousal in Drive M - Turning segment', marker=COLOR_MOTORIC) %>%
add_trace(y = ~PP_Prior, name = 'Arousal in Drive F - Under prior stressor', marker=COLOR_FAILURE_PRIOR) %>%
add_trace(y = ~PP_Dev, name = 'Arousal in Drive F - Unintended acceleration', marker=COLOR_FAILURE) %>%
add_segments(x="#05", xend="#31", y = THRESHOLD_MILD, yend = THRESHOLD_MILD, name="Threshold",
line=list(color="blue", dash = 'dot')) %>%
# add_segments(x="#05", xend="#31", y = THRESHOLD_EXTREME, yend = THRESHOLD_EXTREME, name="Threshold: Extreme Change of PP",
# line=list(color="darkred", dash = 'dot')) %>%
layout(yaxis = yAxis, barmode = 'group', title="Stressor = Motoric")
htmltools::tagList(fig_Motoric)
A marker object has been specified, but markers is not in the mode
Adding markers to the mode...
A marker object has been specified, but markers is not in the mode
Adding markers to the mode...
library(nlme)
combinedDf$Subject = as.factor(combinedDf$Subject)
combinedDf$Activity = as.factor(combinedDf$Activity)
combinedDf$PP_Dev_Group = ifelse(combinedDf$PP_Dev > THRESHOLD_MILD, 1, 0)
Linear model with all variables
combinedDfNoOutlier <- combinedDf[combinedDf$Subject != "#05",]
linearModel1 <- lm(PP_Dev ~
+ abs(PP_Dev_2_Straight)
+ abs(PP_Dev_3_Straight)
+ abs(PP_Dev_2_Turning)
+ abs(PP_Dev_3_Turning)
+ Std_PP_2_Straight
+ Std_PP_3_Straight
+ Std_PP_2_Turning
+ Std_PP_3_Turning
+ abs(PP_Prior)
+ factor(Activity),
data=combinedDf)
# anova(model)
summary(linearModel1)
Call:
lm(formula = PP_Dev ~ +abs(PP_Dev_2_Straight) + abs(PP_Dev_3_Straight) +
abs(PP_Dev_2_Turning) + abs(PP_Dev_3_Turning) + Std_PP_2_Straight +
Std_PP_3_Straight + Std_PP_2_Turning + Std_PP_3_Turning +
abs(PP_Prior) + factor(Activity), data = combinedDf)
Residuals:
Min 1Q Median 3Q Max
-0.054837 -0.031566 -0.006179 0.016176 0.073043
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.01505 0.06171 0.244 0.8128
abs(PP_Dev_2_Straight) -0.67715 0.35214 -1.923 0.0866 .
abs(PP_Dev_3_Straight) -0.90476 0.37179 -2.434 0.0378 *
abs(PP_Dev_2_Turning) 1.29154 0.41215 3.134 0.0121 *
abs(PP_Dev_3_Turning) 0.65586 0.40513 1.619 0.1399
Std_PP_2_Straight 0.12427 0.88972 0.140 0.8920
Std_PP_3_Straight 0.95634 0.53863 1.776 0.1095
Std_PP_2_Turning 0.02239 0.94717 0.024 0.9817
Std_PP_3_Turning -1.57139 0.74405 -2.112 0.0639 .
abs(PP_Prior) 0.59450 0.29811 1.994 0.0773 .
factor(Activity)M 0.07630 0.03754 2.033 0.0726 .
factor(Activity)NO -0.13039 0.05580 -2.337 0.0442 *
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.05362 on 9 degrees of freedom
Multiple R-squared: 0.8315, Adjusted R-squared: 0.6256
F-statistic: 4.039 on 11 and 9 DF, p-value: 0.02262
plot(linearModel1)




linearModel1 <- lm(PP_Dev ~
+ PP_Dev_2
+ PP_Dev_3
+ Std_PP_2
+ Std_PP_3,
data=combinedDfNoOutlier)
# anova(model)
summary(linearModel1)
Call:
lm(formula = PP_Dev ~ +PP_Dev_2 + PP_Dev_3 + Std_PP_2 + Std_PP_3,
data = combinedDfNoOutlier)
Residuals:
Min 1Q Median 3Q Max
-0.12047 -0.04606 -0.01017 0.04443 0.10684
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -0.13336 0.07723 -1.727 0.1048
PP_Dev_2 0.16542 0.14765 1.120 0.2802
PP_Dev_3 -0.33968 0.22814 -1.489 0.1572
Std_PP_2 0.08517 0.45813 0.186 0.8550
Std_PP_3 2.50981 1.04105 2.411 0.0292 *
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.07381 on 15 degrees of freedom
Multiple R-squared: 0.4679, Adjusted R-squared: 0.3261
F-statistic: 3.298 on 4 and 15 DF, p-value: 0.0397
plot(linearModel1)




Linear Model from Drive C
linearModelC <- lm(PP_Dev ~
PP_Dev_2_Straight
+ PP_Dev_2_Turning
+ Std_PP_2_Straight
+ Std_PP_2_Turning,
data=combinedDf)
# anova(model)
summary(linearModelC)
Call:
lm(formula = PP_Dev ~ PP_Dev_2_Straight + PP_Dev_2_Turning +
Std_PP_2_Straight + Std_PP_2_Turning, data = combinedDf)
Residuals:
Min 1Q Median 3Q Max
-0.13555 -0.05433 0.00251 0.05596 0.12635
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.02351 0.05388 0.436 0.668
PP_Dev_2_Straight -0.02887 0.26153 -0.110 0.913
PP_Dev_2_Turning 0.19976 0.30675 0.651 0.524
Std_PP_2_Straight 1.13112 0.84826 1.333 0.201
Std_PP_2_Turning -0.62211 0.92511 -0.672 0.511
Residual standard error: 0.08441 on 16 degrees of freedom
Multiple R-squared: 0.258, Adjusted R-squared: 0.07249
F-statistic: 1.391 on 4 and 16 DF, p-value: 0.2816
plot(linearModelC)




linearModelC_Segments <- lm(PP_Dev ~
PP_Dev_2
+ Std_PP_2,
data=combinedDf)
# anova(model)
summary(linearModelC_Segments)
Call:
lm(formula = PP_Dev ~ PP_Dev_2 + Std_PP_2, data = combinedDf)
Residuals:
Min 1Q Median 3Q Max
-0.14869 -0.05352 -0.01075 0.06704 0.13707
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.02784 0.04663 0.597 0.558
PP_Dev_2 0.15451 0.11497 1.344 0.196
Std_PP_2 0.47780 0.40255 1.187 0.251
Residual standard error: 0.08518 on 18 degrees of freedom
Multiple R-squared: 0.1498, Adjusted R-squared: 0.05531
F-statistic: 1.585 on 2 and 18 DF, p-value: 0.2322
plot(linearModelC_Segments)




Linear Model from Drive M
linearModelM <- lm(PP_Dev ~
PP_Dev_3
+ Std_PP_3
+ factor(Activity),
data=combinedDfNoOutlier)
# anova(model)
summary(linearModelM)
Call:
lm(formula = PP_Dev ~ PP_Dev_3 + Std_PP_3 + factor(Activity),
data = combinedDfNoOutlier)
Residuals:
Min 1Q Median 3Q Max
-0.08243 -0.05948 -0.00697 0.05039 0.10987
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -0.110401 0.082369 -1.340 0.2001
PP_Dev_3 -0.070627 0.178377 -0.396 0.6977
Std_PP_3 2.020000 0.947378 2.132 0.0499 *
factor(Activity)M 0.068144 0.044012 1.548 0.1424
factor(Activity)NO -0.001664 0.038375 -0.043 0.9660
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.07078 on 15 degrees of freedom
Multiple R-squared: 0.5107, Adjusted R-squared: 0.3802
F-statistic: 3.914 on 4 and 15 DF, p-value: 0.02269
plot(linearModelM)




linearModelM <- lm(PP_Dev ~
PP_Dev_3_Straight
+ PP_Dev_3_Turning
+ Std_PP_3_Straight
+ Std_PP_3_Turning,
data=combinedDfNoOutlier)
# anova(model)
summary(linearModelM)
Call:
lm(formula = PP_Dev ~ PP_Dev_3_Straight + PP_Dev_3_Turning +
Std_PP_3_Straight + Std_PP_3_Turning, data = combinedDfNoOutlier)
Residuals:
Min 1Q Median 3Q Max
-0.09868 -0.05695 -0.01233 0.06261 0.10188
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -0.15580 0.07868 -1.980 0.0663 .
PP_Dev_3_Straight -0.74334 0.36299 -2.048 0.0585 .
PP_Dev_3_Turning 0.64682 0.42651 1.517 0.1502
Std_PP_3_Straight 0.88491 0.69611 1.271 0.2230
Std_PP_3_Turning 1.81284 0.93698 1.935 0.0721 .
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.07454 on 15 degrees of freedom
Multiple R-squared: 0.4574, Adjusted R-squared: 0.3127
F-statistic: 3.162 on 4 and 15 DF, p-value: 0.04517
plot(linearModelM)




# Export the anova table
library(xtable)
lmCoeffs <- summary(linearModel1)$coefficients
lmAnova <- anova(linearModel1)
print(xtable(lmCoeffs, digits=c(0,5,5,5,5)))
% latex table generated in R 3.6.1 by xtable 1.8-4 package
% Fri Jul 10 02:45:47 2020
\begin{table}[ht]
\centering
\begin{tabular}{rrrrr}
\hline
& Estimate & Std. Error & t value & Pr($>$$|$t$|$) \\
\hline
(Intercept) & -0.13336 & 0.07723 & -1.72671 & 0.10475 \\
PP\_Dev\_2 & 0.16542 & 0.14765 & 1.12038 & 0.28017 \\
PP\_Dev\_3 & -0.33968 & 0.22814 & -1.48892 & 0.15723 \\
Std\_PP\_2 & 0.08517 & 0.45813 & 0.18591 & 0.85500 \\
Std\_PP\_3 & 2.50981 & 1.04105 & 2.41085 & 0.02920 \\
\hline
\end{tabular}
\end{table}
print(xtable(lmAnova), digits=c(0,5,5,5,5))
% latex table generated in R 3.6.1 by xtable 1.8-4 package
% Fri Jul 10 02:45:47 2020
\begin{table}[ht]
\centering
\begin{tabular}{lrrrrr}
\hline
& Df & Sum Sq & Mean Sq & F value & Pr($>$F) \\
\hline
PP\_Dev\_2 & 1 & 0.01 & 0.01 & 2.37 & 0.1445 \\
PP\_Dev\_3 & 1 & 0.01 & 0.01 & 1.31 & 0.2706 \\
Std\_PP\_2 & 1 & 0.02 & 0.02 & 3.70 & 0.0735 \\
Std\_PP\_3 & 1 & 0.03 & 0.03 & 5.81 & 0.0292 \\
Residuals & 15 & 0.08 & 0.01 & & \\
\hline
\end{tabular}
\end{table}
combinedDf$PP_Dev <- NULL
combinedDf$Subject <- NULL
combinedDf$Activity_NO <- ifelse(combinedDf$Activity == "NO", 1, 0)
combinedDf$Activity_C <- ifelse(combinedDf$Activity == "C", 1, 0)
combinedDf$Activity_M <- ifelse(combinedDf$Activity == "M", 1, 0)
combinedDf$Activity <- NULL
combinedDf$PP_Dev_1_Turning <- NULL
combinedDf$Std_PP_2_Straight <- NULL
combinedDf$Std_PP_2_Turning <- NULL
combinedDf$Std_PP_3_Straight <- NULL
combinedDf$Std_PP_3_Turning <- NULL
# According to Linear model
combinedDf$PP_Dev_2_Straight <- abs(combinedDf$PP_Dev_2_Straight)
combinedDf$PP_Dev_3_Straight <- abs(combinedDf$PP_Dev_3_Straight)
combinedDf$PP_Dev_2_Turning <- abs(combinedDf$PP_Dev_2_Turning)
combinedDf$PP_Dev_3_Turning <- abs(combinedDf$PP_Dev_3_Turning)
combinedDf$PP_Prior <- abs(combinedDf$PP_Prior) # NULL
combinedDf$Class <- ifelse(combinedDf$PP_Dev_Group == 1, T, F)
combinedDf$PP_Dev_Group <- NULL
print(names(combinedDf))
[1] "PP_Prior" "PP_Dev_2" "PP_Dev_3" "Std_PP_2" "Std_PP_3" "PP_Dev_2_Straight"
[7] "PP_Dev_3_Straight" "PP_Dev_2_Turning" "PP_Dev_3_Turning" "Activity_NO" "Activity_C" "Activity_M"
[13] "Class"
# library(mefa)
# combinedDf <- rep(combinedDf, 10)
set.seed(39)
n_folds <- 3
params <- param <- list(objective = "binary:logistic",
booster = "gbtree",
eval_metric = "auc",
eta = 0.1,
max_depth = 10,
alpha = 1,
lambda = 0,
gamma = 0.45,
min_child_weight = 0.3,
subsample = 1,
colsample_bytree = 1)
# XGBoost Model
xgb_m <- xgb.cv( params = param,
data = as.matrix(combinedDf %>% select(-Class)) ,
label = combinedDf$Class,
nrounds = 100,
verbose = F,
prediction = T,
maximize = T, # Change this value to F will help to run with more itineration
nfold = n_folds,
metrics = c("auc", "error"),
early_stopping_rounds = 50,
stratified = T,
scale_pos_weight = 7/14)
# xgb_m$evaluation_log[xgb_m$best_iteration,"test_auc_mean"]
xgb_m$evaluation_log[xgb_m$best_iteration,]
NA
# Prediction
combinedDf$clsPred <- round(xgb_m$pred)
computePerformanceResults <- function(sdat){
sdat = sdat[complete.cases(sdat),]
acc = sum(sdat[,1] == sdat[,2])/nrow(sdat)
conf_mat = table(sdat)
specif = conf_mat[1,1]/sum(conf_mat[,1])
sensiv = conf_mat[2,2]/sum(conf_mat[,2])
preci = conf_mat[2,2]/sum(conf_mat[2,])
npv = conf_mat[1,1]/sum(conf_mat[1,])
return(c(acc,specif,sensiv,preci,npv))
}
# Get average performance
performance <- computePerformanceResults(combinedDf %>% select(Class, clsPred))
acc <- performance[1]
prec <- performance[4]
recall <- performance[3]
spec <- performance[2]
npv <- performance[5]
f1 <- (2 * recall * prec) / (recall + prec)
auc <- as.numeric(xgb_m$evaluation_log[xgb_m$best_iteration, "test_auc_mean"])
print(paste("Accuracy=", round(acc, 2)))
[1] "Accuracy= 0.9"
print(paste("Precision=", round(prec, 2)))
[1] "Precision= 0.92"
print(paste("Recall=", round(recall, 2)))
[1] "Recall= 0.92"
print(paste("Specificity=", round(spec, 2)))
[1] "Specificity= 0.88"
print(paste("NPV=", round(npv, 2)))
[1] "NPV= 0.88"
print(paste("F1=", round(f1, 2)))
[1] "F1= 0.92"
print(paste("AUC=", round(auc, 2)))
[1] "AUC= 0.91"
# Importance
bst <- xgboost( params = param,
data = as.matrix(combinedDf %>% select(-Class)) ,
label = combinedDf$Class,
nrounds = 100,
verbose = F,
prediction = T,
maximize = T, # Change this value to F will help to run with more itineration
nfold = n_folds,
metrics = c("auc", "error"),
early_stopping_rounds = 50,
stratified = T,
scale_pos_weight = 1)
importanceDf <- xgb.importance(colnames(combinedDf), model = bst)
print(importanceDf)
library(pROC)
dfROC <- pROC::roc(response = ifelse(combinedDf$Class==T, 1, 0),
predictor = round(xgb_m$pred),
levels=c(0, 1), direction = "<")
# it = which.max(xgb_m$evaluation_log$test_auc_mean)
# best.iter = xgb_m$evaluation_log$iter[it]
# best.iter
plot(pROC::roc(response = ifelse(combinedDf$Class==T, 1, 0),
predictor = round(xgb_m$pred),
levels=c(0, 1), direction = "<"),
legacy.axes = TRUE,
main="ROC Curve",
lwd=1.5)

Important features
# Eleminate #5 who has an exceptional data to find a better threshold
stdPP3 <- sort(importantFeaturesDf$Std_PP_3, decreasing = T)[2:length(importantFeaturesDf$Std_PP_3)]
stdPP3Array <- matrix(stdPP3 ,nrow = 1,ncol = length(stdPP3))
maxStdPP3 <- sort(importantFeaturesDf$Std_PP_3, decreasing = T)[2]
PP_DEV_3_THRESHOLD <- otsu(stdPP3Array, range=c(min(stdPP3), maxStdPP3)) # Expected Threshold = 0.088
print(paste0('Threshold: ', PP_DEV_3_THRESHOLD))
[1] "Threshold: 0.0881111526518663"
importantFeaturesDf$PP_Dev_3_Group <- ifelse(importantFeaturesDf$Std_PP_3 > PP_DEV_3_THRESHOLD, 1, 0)
write.csv(importantFeaturesDf, "../outputs/importantFeatures.csv")
Venn diagram
library(VennDiagram)
library(RColorBrewer)
M_Low <- rownames(importantFeaturesDf[importantFeaturesDf$PP_Dev_3_Group==0,])
M_High <- rownames(importantFeaturesDf[importantFeaturesDf$PP_Dev_3_Group==1,])
F_Low <- rownames(importantFeaturesDf[importantFeaturesDf$PP_Dev_Group==0,])
F_High <- rownames(importantFeaturesDf[importantFeaturesDf$PP_Dev_Group==1,])
jpeg("../plots/venn/venn_All.png", res=150, width=900)
venn.plot <- venn.diagram(
list(M_Low, F_Low, M_High, F_High), NULL,
fill=c("blue", "blue", "red", "red"),
alpha=c(0.5,0.5,0.5,0.5),
resolution = 150,
cex = 1,
cat.fontface=1,
category.names=c("Drive=M\n SD=Low\n", "Drive=F\n Arousal=Low\n", "Drive=M\n SD=High\n", "Drive=F\n Arousal=High\n")
)
grid.draw(venn.plot)
dev.off()
null device
1
#
# jpeg("../plots/venn/venn_High.png", res=150, width=700)
# venn.plot <- venn.diagram(
# list(M_High, F_High), NULL,
# fill=c("pink", "red"),
# alpha=c(0.5,0.5),
# resolution = 150,
# cex = 1,
# cat.fontface=1,
# category.names=c("Drive=M", "Drive=F")
# )
# grid.draw(venn.plot)
# dev.off()
Plot feature importance
yAxis <- list(
title = 'Importance',
range=c(0.0, 1.0)
)
xAxis <- list(
title = ''
)
importanceDf$FeatureName <- lapply(importanceDf$Feature, function(x) {
ifelse(x=="Std_PP_3", "SD of Arousal\n in Drive M",
ifelse(x=="PP_Dev_2_Turning", "Arousal in Drive C\nat turning segments",
ifelse(x=="Activity_C", "Prior stressor\n is Cognitive", x)))
})
fig_Importance <- plot_ly(importanceDf, x = ~FeatureName, y = ~Gain, type = 'bar', name = 'Gain', width=600) %>%
add_trace(y = ~Cover, name = 'Cover') %>%
add_trace(y = ~Frequency, name = 'Frequency') %>%
layout(yaxis = yAxis, xaxis=xAxis, barmode = 'group', title="Feature Importance") %>%
config(.Last.value, mathjax = 'cdn')
htmltools::tagList(fig_Importance)
Feature
classColors <- c("blue", "red")
figStdVsDev <- plot_ly(data = importantFeaturesDf, x = ~Std_PP_3, y = ~PP_Dev,
color=~factor(PP_Dev_Group), colors=classColors,
marker=list(text="X")) %>%
layout(xaxis=list(title="SD of Arousal in Motoric Drive \n Hyphenated line indicates discriminative boundary"), yaxis=list(title="Arousal at catastrophic event"), showscale=F) %>%
layout(shapes=list(
list(x0=0.088, x1=0.088, y0=-0.1, y1=0.25, line=list(dash="dot", width=1, color="green"))
))
htmltools::tagList(figStdVsDev)
No trace type specified:
Based on info supplied, a 'scatter' trace seems appropriate.
Read more about this trace type -> https://plot.ly/r/reference/#scatter
No scatter mode specifed:
Setting the mode to markers
Read more about this attribute -> https://plot.ly/r/reference/#scatter-mode
'layout' objects don't have these attributes: 'showscale'
Valid attributes include:
'font', 'title', 'autosize', 'width', 'height', 'margin', 'paper_bgcolor', 'plot_bgcolor', 'separators', 'hidesources', 'showlegend', 'colorway', 'datarevision', 'uirevision', 'editrevision', 'selectionrevision', 'template', 'modebar', 'meta', 'transition', '_deprecated', 'clickmode', 'dragmode', 'hovermode', 'hoverdistance', 'spikedistance', 'hoverlabel', 'selectdirection', 'grid', 'calendar', 'xaxis', 'yaxis', 'ternary', 'scene', 'geo', 'mapbox', 'polar', 'radialaxis', 'angularaxis', 'direction', 'orientation', 'editType', 'legend', 'annotations', 'shapes', 'images', 'updatemenus', 'sliders', 'colorscale', 'coloraxis', 'metasrc', 'barmode', 'bargap', 'mapType'
No trace type specified:
Based on info supplied, a 'scatter' trace seems appropriate.
Read more about this trace type -> https://plot.ly/r/reference/#scatter
No scatter mode specifed:
Setting the mode to markers
Read more about this attribute -> https://plot.ly/r/reference/#scatter-mode
'layout' objects don't have these attributes: 'showscale'
Valid attributes include:
'font', 'title', 'autosize', 'width', 'height', 'margin', 'paper_bgcolor', 'plot_bgcolor', 'separators', 'hidesources', 'showlegend', 'colorway', 'datarevision', 'uirevision', 'editrevision', 'selectionrevision', 'template', 'modebar', 'meta', 'transition', '_deprecated', 'clickmode', 'dragmode', 'hovermode', 'hoverdistance', 'spikedistance', 'hoverlabel', 'selectdirection', 'grid', 'calendar', 'xaxis', 'yaxis', 'ternary', 'scene', 'geo', 'mapbox', 'polar', 'radialaxis', 'angularaxis', 'direction', 'orientation', 'editType', 'legend', 'annotations', 'shapes', 'images', 'updatemenus', 'sliders', 'colorscale', 'coloraxis', 'metasrc', 'barmode', 'bargap', 'mapType'
classColors <- c("blue", "red")
figStdVsDev <- plot_ly(data = importantFeaturesDf, x = ~abs(PP_Dev_2_Turning), y = ~PP_Dev,
color=~factor(PP_Dev_Group), colors=classColors,
marker=list(text="X")) %>%
layout(xaxis=list(title="SD of Arousal in Motoric Drive"), yaxis=list(title="Arousal at catastrophic event")) %>%
layout(shapes=list(
list(x0=0.088, x1=0.088, y0=-0.1, y1=0.25, line=list(dash="dot", width=1))
))
htmltools::tagList(figStdVsDev)
No trace type specified:
Based on info supplied, a 'scatter' trace seems appropriate.
Read more about this trace type -> https://plot.ly/r/reference/#scatter
No scatter mode specifed:
Setting the mode to markers
Read more about this attribute -> https://plot.ly/r/reference/#scatter-mode
No trace type specified:
Based on info supplied, a 'scatter' trace seems appropriate.
Read more about this trace type -> https://plot.ly/r/reference/#scatter
No scatter mode specifed:
Setting the mode to markers
Read more about this attribute -> https://plot.ly/r/reference/#scatter-mode
classColors <- c("blue", "red")
figStdVsDev <- plot_ly(data = importantFeaturesDf, y = ~abs(PP_Dev_2_Turning), x = ~Std_PP_3,
color=~factor(PP_Dev_Group), colors=classColors,
marker=list(text="X")) %>%
layout(xaxis=list(title="SD of Arousal in Motoric Drive"), yaxis=list(title="Arousal at catastrophic event"), showscale=F) %>%
layout(shapes=list(
list(x0=0.088, x1=0.088, y0=-0.1, y1=0.25, line=list(dash="dot", width=1))
))
htmltools::tagList(figStdVsDev)
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3J9CnNvdXJjZSgnLi4vc2V0dGluZ3Mvc2V0dGluZ3MuUicpCnNvdXJjZSgnY29tbW9uRnVuY3Rpb25zLlInKQpgYGAKCmBgYHtyfQpkcml2ZTEgPC0gcmVhZC5jc3YoJy4uL2RhdGEvcHJvY2Vzc2VkL2FuYWx5c2lzL1RUMV9Ecml2ZV8xX1BQLmNzdicpCmRyaXZlMiA8LSByZWFkLmNzdignLi4vZGF0YS9wcm9jZXNzZWQvQW5hbHlzaXMvVFQxX0RyaXZlXzJfUFAuY3N2JykKZHJpdmUzIDwtIHJlYWQuY3N2KCcuLi9kYXRhL3Byb2Nlc3NlZC9BbmFseXNpcy9UVDFfRHJpdmVfM19QUC5jc3YnKQpkcml2ZTQgPC0gcmVhZC5jc3YoJy4uL2RhdGEvcHJvY2Vzc2VkL0FuYWx5c2lzL1RUMV9Ecml2ZV80X1BQLmNzdicsIHN0cmluZ3NBc0ZhY3RvcnMgPSBUKQpgYGAKCmBgYHtyfQpzZXQuc2VlZCg0MykKY29tYmluZWREZiA8LSBjYmluZChkcml2ZTQsIAogICAgICAgICAgICAgICAgICAgIGRyaXZlMSRNZWFuUFBfU2VnMCwgCiAgICAgICAgICAgICAgICAgICAgZHJpdmUyJE1lYW5QUCwgZHJpdmUzJE1lYW5QUCwKICAgICAgICAgICAgICAgICAgICBkcml2ZTIkU3RkUFAsIGRyaXZlMyRTdGRQUCwKICAgICAgICAgICAgICAgICAgICBkcml2ZTIkTWVhblBQX1NlZ01heCwgZHJpdmUzJE1lYW5QUF9TZWdNYXgsIAogICAgICAgICAgICAgICAgICAgIGRyaXZlMiRNZWFuUFBfU2VnMCwgZHJpdmUzJE1lYW5QUF9TZWcwLAogICAgICAgICAgICAgICAgICAgIGRyaXZlMiRTdGRQUF9TZWdNYXgsIGRyaXZlMyRTdGRQUF9TZWdNYXgsIAogICAgICAgICAgICAgICAgICAgIGRyaXZlMiRTdGRQUF9TZWcwLCBkcml2ZTMkU3RkUFBfU2VnMAogICAgICAgICAgICAgICAgICApCm5hbWVzKGNvbWJpbmVkRGYpIDwtIGMobmFtZXMoZHJpdmU0KSwgCiAgICAgICAgICAgICAgICAgICAgICAgIlBQX0Rldl8xX1R1cm5pbmciLAogICAgICAgICAgICAgICAgICAgICAgICJQUF9EZXZfMiIsICJQUF9EZXZfMyIsIAogICAgICAgICAgICAgICAgICAgICAgICJTdGRfUFBfMiIsICJTdGRfUFBfMyIsCiAgICAgICAgICAgICAgICAgICAgICAgIlBQX0Rldl8yX1N0cmFpZ2h0IiwgIlBQX0Rldl8zX1N0cmFpZ2h0IiwgCiAgICAgICAgICAgICAgICAgICAgICAgIlBQX0Rldl8yX1R1cm5pbmciLCAiUFBfRGV2XzNfVHVybmluZyIsIAogICAgICAgICAgICAgICAgICAgICAgICJTdGRfUFBfMl9TdHJhaWdodCIsICJTdGRfUFBfM19TdHJhaWdodCIsIAogICAgICAgICAgICAgICAgICAgICAgICJTdGRfUFBfMl9UdXJuaW5nIiwgIlN0ZF9QUF8zX1R1cm5pbmciCiAgICAgICAgICAgICAgICAgICAgICAgKQoKY29tYmluZWREZiRTdWJqZWN0IDwtIHBhc3RlMCgiIyIsIHN0cl9wYWQoY29tYmluZWREZiRTdWJqZWN0LCAyLCBwYWQ9IjAiKSkKCiMgY29tYmluZWREZiRQUF9EZXZfMl9UdXJuaW5nIDwtIGlmZWxzZShjb21iaW5lZERmJFBQX0Rldl8yX1R1cm5pbmcgPiAwLCBjb21iaW5lZERmJFBQX0Rldl8yX1R1cm5pbmcsIGNvbWJpbmVkRGYkUFBfRGV2XzJfU3RyYWlnaHQpCmBgYAoKYGBge3J9CmNvbWJpbmVkRGZfTm9TdHJlc3NvciA8LSBjb21iaW5lZERmW2NvbWJpbmVkRGYkQWN0aXZpdHkgPT0gIk5PIixdCmNvbWJpbmVkRGZfQ29nbml0aXZlIDwtIGNvbWJpbmVkRGZbY29tYmluZWREZiRBY3Rpdml0eSA9PSAiQyIsXQpjb21iaW5lZERmX01vdG9yaWMgPC0gY29tYmluZWREZltjb21iaW5lZERmJEFjdGl2aXR5ID09ICJNIixdCgpjb21iaW5lZERmX05vU3RyZXNzb3IkU3ViamVjdCA8LSBhcy5mYWN0b3IoY29tYmluZWREZl9Ob1N0cmVzc29yJFN1YmplY3QpCmNvbWJpbmVkRGZfQ29nbml0aXZlJFN1YmplY3QgPC0gYXMuZmFjdG9yKGNvbWJpbmVkRGZfQ29nbml0aXZlJFN1YmplY3QpCmNvbWJpbmVkRGZfTW90b3JpYyRTdWJqZWN0IDwtIGFzLmZhY3Rvcihjb21iaW5lZERmX01vdG9yaWMkU3ViamVjdCkKYGBgCgpgYGB7cn0KQ09MT1JfTk9STUFMIDwtIGxpc3QoY29sb3I9J3JnYigxMjAsMTIwLDEyMCknKQpDT0xPUl9DT0dOSVRJVkUgPC0gbGlzdChjb2xvcj0ncmdiKDE1OCwyMDIsMjI1KScpCkNPTE9SX01PVE9SSUMgPC0gbGlzdChjb2xvcj0ncmdiKDU4LDIwMCwyMjUpJykKQ09MT1JfRkFJTFVSRV9QUklPUiA8LSBsaXN0KGNvbG9yPSdyZ2IoMTU4LDIwMiwyMjUpJykKQ09MT1JfRkFJTFVSRSA8LSBsaXN0KGNvbG9yPSdyZWQnKQoKeUF4aXMgPC0gbGlzdCgKICB0aXRsZSA9ICdQZXJpbmFzYWwgUGVyc3BpcmF0aW9uIChMb2cpJywKICByYW5nZT1jKC0wLjMsIDAuNSkKKQoKIyBBcHBseSBPdHN1IGFsZ29yaXRobSB0byBzZWxlY3QgdGhyZXNob2xkCnBwRGV2IDwtIGNvbWJpbmVkRGYkUFBfRGV2CnBwRGV2QXJyYXkgPC0gbWF0cml4KHBwRGV2ICxucm93ID0gMSxuY29sID0gbGVuZ3RoKHBwRGV2KSkKICAKVEhSRVNIT0xEX01JTEQgPSBvdHN1KHBwRGV2QXJyYXksIHJhbmdlPWMobWluKHBwRGV2KSwgbWF4KHBwRGV2KSkpICMgRXhwZWN0ZWQgVGhyZXNob2xkID4gMC4wNDIKcHJpbnQocGFzdGUwKCdUaHJlc2hvbGQ6ICcsIFRIUkVTSE9MRF9NSUxEKSkKCk1BUktFUl9MSU5FX01JTEQgPSBsaXN0KGNvbG9yPSJibHVlIikKTUFSS0VSX0xJTkVfRVhUUkVNRSA9IGxpc3QoY29sb3I9InJlZCIpCmBgYAoKYGBge3IsIHdhcm5pbmc9Rn0KZmlnX05vU3RyZXNzb3IgPC0gcGxvdF9seShjb21iaW5lZERmX05vU3RyZXNzb3IsIHggPSB+U3ViamVjdCwgeSA9IH5QUF9EZXZfMl9TdHJhaWdodCwgdHlwZSA9ICdiYXInLCBuYW1lID0gJ0NvZ25pdGl2ZSAtIE1lYW4gUFAgKFN0cmFpZ2h0KScsIG1hcmtlcj1DT0xPUl9DT0dOSVRJVkUpICU+JQogIGFkZF90cmFjZSh5ID0gflBQX0Rldl8zX1N0cmFpZ2h0LCBuYW1lID0gJ01vdG9yaWMgLSBNZWFuIFBQIChTdHJhaWdodCknLCBtYXJrZXI9Q09MT1JfTU9UT1JJQykgJT4lIAogIGFkZF90cmFjZSh5ID0gflBQX0Rldl8yX1R1cm5pbmcsIG5hbWUgPSAnQ29nbml0aXZlIC0gTWVhbiBQUCAoVHVybmluZyknLCBtYXJrZXI9Q09MT1JfQ09HTklUSVZFKSAlPiUgCiAgYWRkX3RyYWNlKHkgPSB+UFBfRGV2XzNfVHVybmluZywgbmFtZSA9ICdNb3RvcmljIC0gTWVhbiBQUCAoVHVybmluZyknLCBtYXJrZXI9Q09MT1JfTU9UT1JJQykgJT4lIAogIGFkZF90cmFjZSh5ID0gflBQX1ByaW9yLCBuYW1lID0gJ0ZhaWx1cmUgLSBQcmlvciBQUCcsIG1hcmtlcj1DT0xPUl9GQUlMVVJFX1BSSU9SKSAlPiUgCiAgYWRkX3RyYWNlKHkgPSB+UFBfRGV2LCBuYW1lID0gJ0ZhaWx1cmUgLSBQUCBEZXZpYXRpb24nLCBtYXJrZXI9Q09MT1JfRkFJTFVSRSkgJT4lIAogIGFkZF9zZWdtZW50cyh4PSIjMDEiLCB4ZW5kPSIjNDEiLCB5ID0gVEhSRVNIT0xEX01JTEQsIHllbmQgPSBUSFJFU0hPTERfTUlMRCwgbmFtZT0iVGhyZXNob2xkOiBNaWxkIENoYW5nZSBvZiBQUCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmU9bGlzdChjb2xvcj0iYmx1ZSIsIGRhc2ggPSAnZG90JykpICU+JQogICMgYWRkX3NlZ21lbnRzKHg9IiMwMSIsIHhlbmQ9IiM0MSIsIHkgPSBUSFJFU0hPTERfRVhUUkVNRSwgeWVuZCA9IFRIUkVTSE9MRF9FWFRSRU1FLCBuYW1lPSJUaHJlc2hvbGQ6IEV4dHJlbWUgQ2hhbmdlIG9mIFBQIiwKICAjICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5lPWxpc3QoY29sb3I9ImRhcmtyZWQiLCBkYXNoID0gJ2RvdCcpKSAlPiUKICBsYXlvdXQoeWF4aXMgPSB5QXhpcywgYmFybW9kZSA9ICdncm91cCcsIHRpdGxlPSJObyBTdHJlc3NvciIpCgpodG1sdG9vbHM6OnRhZ0xpc3QoZmlnX05vU3RyZXNzb3IpCmBgYAoKYGBge3IsIHdhcm5pbmc9Rn0KZmlnX0NvZ25pdGl2ZSA8LSBwbG90X2x5KGNvbWJpbmVkRGZfQ29nbml0aXZlLCB4ID0gflN1YmplY3QsIHkgPSB+UFBfRGV2XzJfU3RyYWlnaHQsIHR5cGUgPSAnYmFyJywgbmFtZSA9ICdDb2duaXRpdmUgLSBNZWFuIFBQIChTdHJhaWdodCknLCBtYXJrZXI9Q09MT1JfQ09HTklUSVZFKSAlPiUKICBhZGRfdHJhY2UoeSA9IH5QUF9EZXZfM19TdHJhaWdodCwgbmFtZSA9ICdNb3RvcmljIC0gTWVhbiBQUCAoU3RyYWlnaHQpJywgbWFya2VyPUNPTE9SX01PVE9SSUMpICU+JSAKICBhZGRfdHJhY2UoeSA9IH5QUF9EZXZfMl9UdXJuaW5nLCBuYW1lID0gJ0NvZ25pdGl2ZSAtIE1lYW4gUFAgKFR1cm5pbmcpJywgbWFya2VyPUNPTE9SX0NPR05JVElWRSkgJT4lIAogIGFkZF90cmFjZSh5ID0gflBQX0Rldl8zX1R1cm5pbmcsIG5hbWUgPSAnTW90b3JpYyAtIE1lYW4gUFAgKFR1cm5pbmcpJywgbWFya2VyPUNPTE9SX01PVE9SSUMpICU+JSAKICBhZGRfdHJhY2UoeSA9IH5QUF9QcmlvciwgbmFtZSA9ICdGYWlsdXJlIC0gUHJpb3IgUFAnLCBtYXJrZXI9Q09MT1JfRkFJTFVSRV9QUklPUikgJT4lIAogIGFkZF90cmFjZSh5ID0gflBQX0RldiwgbmFtZSA9ICdGYWlsdXJlIC0gUFAgRGV2aWF0aW9uJywgbWFya2VyPUNPTE9SX0ZBSUxVUkUpICU+JSAKICBhZGRfc2VnbWVudHMoeD0iIzAyIiwgeGVuZD0iIzIyIiwgeSA9IFRIUkVTSE9MRF9NSUxELCB5ZW5kID0gVEhSRVNIT0xEX01JTEQsIG5hbWU9IlRocmVzaG9sZDogTWlsZCBDaGFuZ2Ugb2YgUFAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5lPWxpc3QoY29sb3I9ImJsdWUiLCBkYXNoID0gJ2RvdCcpKSAlPiUKICAjIGFkZF9zZWdtZW50cyh4PSIjMDIiLCB4ZW5kPSIjMjIiLCB5ID0gVEhSRVNIT0xEX0VYVFJFTUUsIHllbmQgPSBUSFJFU0hPTERfRVhUUkVNRSwgbmFtZT0iVGhyZXNob2xkOiBFeHRyZW1lIENoYW5nZSBvZiBQUCIsCiAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZT1saXN0KGNvbG9yPSJkYXJrcmVkIiwgZGFzaCA9ICdkb3QnKSkgJT4lCiAgbGF5b3V0KHlheGlzID0geUF4aXMsIGJhcm1vZGUgPSAnZ3JvdXAnLCB0aXRsZT0iU3RyZXNzb3IgPSBDb2duaXRpdmUiKQoKaHRtbHRvb2xzOjp0YWdMaXN0KGZpZ19Db2duaXRpdmUpCmBgYAoKCgpgYGB7ciwgd2FybmluZz1GfQpmaWdfTW90b3JpYyA8LSBwbG90X2x5KGNvbWJpbmVkRGZfTW90b3JpYywgeCA9IH5TdWJqZWN0LCB5ID0gflBQX0Rldl8yX1N0cmFpZ2h0LCB0eXBlID0gJ2JhcicsIG5hbWUgPSAnQXJvdXNhbCBpbiBEcml2ZSBDIC0gU3RyYWlnaHQgc2VnbWVudCcsIG1hcmtlcj1DT0xPUl9DT0dOSVRJVkUsIHdpZHRoPTg3MCkgJT4lCiAgYWRkX3RyYWNlKHkgPSB+UFBfRGV2XzNfU3RyYWlnaHQsIG5hbWUgPSAnQXJvdXNhbCBpbiBEcml2ZSBNIC0gU3RyYWlnaHQgc2VnbWVudCcsIG1hcmtlcj1DT0xPUl9NT1RPUklDKSAlPiUgCiAgYWRkX3RyYWNlKHkgPSB+UFBfRGV2XzJfVHVybmluZywgbmFtZSA9ICdBcm91c2FsIGluIERyaXZlIEMgLSBUdXJuaW5nIHNlZ21lbnQnLCBtYXJrZXI9Q09MT1JfQ09HTklUSVZFKSAlPiUgCiAgYWRkX3RyYWNlKHkgPSB+UFBfRGV2XzNfVHVybmluZywgbmFtZSA9ICdBcm91c2FsIGluIERyaXZlIE0gLSBUdXJuaW5nIHNlZ21lbnQnLCBtYXJrZXI9Q09MT1JfTU9UT1JJQykgJT4lCiAgYWRkX3RyYWNlKHkgPSB+UFBfUHJpb3IsIG5hbWUgPSAnQXJvdXNhbCBpbiBEcml2ZSBGIC0gVW5kZXIgcHJpb3Igc3RyZXNzb3InLCBtYXJrZXI9Q09MT1JfRkFJTFVSRV9QUklPUikgJT4lIAogIGFkZF90cmFjZSh5ID0gflBQX0RldiwgbmFtZSA9ICdBcm91c2FsIGluIERyaXZlIEYgLSBVbmludGVuZGVkIGFjY2VsZXJhdGlvbicsIG1hcmtlcj1DT0xPUl9GQUlMVVJFKSAlPiUgCiAgYWRkX3NlZ21lbnRzKHg9IiMwNSIsIHhlbmQ9IiMzMSIsIHkgPSBUSFJFU0hPTERfTUlMRCwgeWVuZCA9IFRIUkVTSE9MRF9NSUxELCBuYW1lPSJUaHJlc2hvbGQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5lPWxpc3QoY29sb3I9ImJsdWUiLCBkYXNoID0gJ2RvdCcpKSAlPiUKICAjIGFkZF9zZWdtZW50cyh4PSIjMDUiLCB4ZW5kPSIjMzEiLCB5ID0gVEhSRVNIT0xEX0VYVFJFTUUsIHllbmQgPSBUSFJFU0hPTERfRVhUUkVNRSwgbmFtZT0iVGhyZXNob2xkOiBFeHRyZW1lIENoYW5nZSBvZiBQUCIsCiAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZT1saXN0KGNvbG9yPSJkYXJrcmVkIiwgZGFzaCA9ICdkb3QnKSkgJT4lCiAgbGF5b3V0KHlheGlzID0geUF4aXMsIGJhcm1vZGUgPSAnZ3JvdXAnLCB0aXRsZT0iU3RyZXNzb3IgPSBNb3RvcmljIikKCmh0bWx0b29sczo6dGFnTGlzdChmaWdfTW90b3JpYykKYGBgCgoKYGBge3J9CmxpYnJhcnkobmxtZSkKY29tYmluZWREZiRTdWJqZWN0ID0gYXMuZmFjdG9yKGNvbWJpbmVkRGYkU3ViamVjdCkKY29tYmluZWREZiRBY3Rpdml0eSA9IGFzLmZhY3Rvcihjb21iaW5lZERmJEFjdGl2aXR5KQpjb21iaW5lZERmJFBQX0Rldl9Hcm91cCA9IGlmZWxzZShjb21iaW5lZERmJFBQX0RldiA+IFRIUkVTSE9MRF9NSUxELCAxLCAwKQpgYGAKCiMjIyBFeHRyYWN0IGRhdGEgZm9yIGltcG9ydGFudCBmZWF0dXJlcwpgYGB7cn0KaW1wb3J0YW50RmVhdHVyZXNEZiA8LSBjb21iaW5lZERmICU+JSBzZWxlY3QoU3ViamVjdCwgU3RkX1BQXzMsIFBQX0Rldl8yX1R1cm5pbmcsIEFjdGl2aXR5LCBQUF9EZXYsIFBQX0Rldl9Hcm91cCkKYGBgCgojIExpbmVhciBtb2RlbCB3aXRoIGFsbCB2YXJpYWJsZXMKYGBge3J9CmNvbWJpbmVkRGZOb091dGxpZXIgPC0gY29tYmluZWREZltjb21iaW5lZERmJFN1YmplY3QgIT0gIiMwNSIsXQpsaW5lYXJNb2RlbDEgPC0gbG0oUFBfRGV2IH4gCiAgICAgICAgICAgICAgKyBhYnMoUFBfRGV2XzJfU3RyYWlnaHQpCiAgICAgICAgICAgICAgKyBhYnMoUFBfRGV2XzNfU3RyYWlnaHQpCiAgICAgICAgICAgICAgKyBhYnMoUFBfRGV2XzJfVHVybmluZykgCiAgICAgICAgICAgICAgKyBhYnMoUFBfRGV2XzNfVHVybmluZykKICAgICAgICAgICAgICArIFN0ZF9QUF8yX1N0cmFpZ2h0CiAgICAgICAgICAgICAgKyBTdGRfUFBfM19TdHJhaWdodAogICAgICAgICAgICAgICsgU3RkX1BQXzJfVHVybmluZwogICAgICAgICAgICAgICsgU3RkX1BQXzNfVHVybmluZwogICAgICAgICAgICAgICsgYWJzKFBQX1ByaW9yKQogICAgICAgICAgICAgICsgZmFjdG9yKEFjdGl2aXR5KSwgCiAgICAgICAgICAgIGRhdGE9Y29tYmluZWREZikKCiMgYW5vdmEobW9kZWwpCnN1bW1hcnkobGluZWFyTW9kZWwxKQpwbG90KGxpbmVhck1vZGVsMSkKYGBgCgpgYGB7cn0KbGluZWFyTW9kZWwxIDwtIGxtKFBQX0RldiB+IAogICAgICAgICAgICAgICsgUFBfRGV2XzIKICAgICAgICAgICAgICArIFBQX0Rldl8zCiAgICAgICAgICAgICAgKyBTdGRfUFBfMgogICAgICAgICAgICAgICsgU3RkX1BQXzMsIAogICAgICAgICAgICBkYXRhPWNvbWJpbmVkRGZOb091dGxpZXIpCgojIGFub3ZhKG1vZGVsKQpzdW1tYXJ5KGxpbmVhck1vZGVsMSkKcGxvdChsaW5lYXJNb2RlbDEpCmBgYAoKCiMgTGluZWFyIE1vZGVsIGZyb20gRHJpdmUgQwpgYGB7cn0KbGluZWFyTW9kZWxDIDwtIGxtKFBQX0RldiB+CiAgICAgICAgICAgICAgUFBfRGV2XzJfU3RyYWlnaHQKICAgICAgICAgICAgICArIFBQX0Rldl8yX1R1cm5pbmcKICAgICAgICAgICAgICArIFN0ZF9QUF8yX1N0cmFpZ2h0CiAgICAgICAgICAgICAgKyBTdGRfUFBfMl9UdXJuaW5nLAogICAgICAgICAgICBkYXRhPWNvbWJpbmVkRGYpCgojIGFub3ZhKG1vZGVsKQpzdW1tYXJ5KGxpbmVhck1vZGVsQykKcGxvdChsaW5lYXJNb2RlbEMpCmBgYAoKYGBge3J9CmxpbmVhck1vZGVsQ19TZWdtZW50cyA8LSBsbShQUF9EZXYgfiAKICAgICAgICAgICAgICBQUF9EZXZfMgogICAgICAgICAgICAgICsgU3RkX1BQXzIsCiAgICAgICAgICAgIGRhdGE9Y29tYmluZWREZikKCiMgYW5vdmEobW9kZWwpCnN1bW1hcnkobGluZWFyTW9kZWxDX1NlZ21lbnRzKQpwbG90KGxpbmVhck1vZGVsQ19TZWdtZW50cykKYGBgCgojIExpbmVhciBNb2RlbCBmcm9tIERyaXZlIE0KYGBge3J9CmxpbmVhck1vZGVsTSA8LSBsbShQUF9EZXYgfiAKICAgICAgICAgICAgICBQUF9EZXZfMwogICAgICAgICAgICAgICsgU3RkX1BQXzMKICAgICAgICAgICAgICArIGZhY3RvcihBY3Rpdml0eSksCiAgICAgICAgICAgIGRhdGE9Y29tYmluZWREZk5vT3V0bGllcikKCiMgYW5vdmEobW9kZWwpCnN1bW1hcnkobGluZWFyTW9kZWxNKQpwbG90KGxpbmVhck1vZGVsTSkKYGBgCmBgYHtyfQpsaW5lYXJNb2RlbE0gPC0gbG0oUFBfRGV2IH4gCiAgICAgICAgICAgICAgUFBfRGV2XzNfU3RyYWlnaHQKICAgICAgICAgICAgICArIFBQX0Rldl8zX1R1cm5pbmcKICAgICAgICAgICAgICArIFN0ZF9QUF8zX1N0cmFpZ2h0CiAgICAgICAgICAgICAgKyBTdGRfUFBfM19UdXJuaW5nLAogICAgICAgICAgICBkYXRhPWNvbWJpbmVkRGZOb091dGxpZXIpCgojIGFub3ZhKG1vZGVsKQpzdW1tYXJ5KGxpbmVhck1vZGVsTSkKcGxvdChsaW5lYXJNb2RlbE0pCmBgYAoKYGBge3J9CiMgRXhwb3J0IHRoZSBhbm92YSB0YWJsZQpsaWJyYXJ5KHh0YWJsZSkKbG1Db2VmZnMgPC0gc3VtbWFyeShsaW5lYXJNb2RlbDEpJGNvZWZmaWNpZW50cwpsbUFub3ZhIDwtIGFub3ZhKGxpbmVhck1vZGVsMSkKCnByaW50KHh0YWJsZShsbUNvZWZmcywgZGlnaXRzPWMoMCw1LDUsNSw1KSkpCnByaW50KHh0YWJsZShsbUFub3ZhKSwgZGlnaXRzPWMoMCw1LDUsNSw1KSkKCmBgYAoKCmBgYHtyfQpjb21iaW5lZERmJFBQX0RldiA8LSBOVUxMCgpjb21iaW5lZERmJFN1YmplY3QgPC0gTlVMTApjb21iaW5lZERmJEFjdGl2aXR5X05PIDwtIGlmZWxzZShjb21iaW5lZERmJEFjdGl2aXR5ID09ICJOTyIsIDEsIDApCmNvbWJpbmVkRGYkQWN0aXZpdHlfQyA8LSBpZmVsc2UoY29tYmluZWREZiRBY3Rpdml0eSA9PSAiQyIsIDEsIDApCmNvbWJpbmVkRGYkQWN0aXZpdHlfTSA8LSBpZmVsc2UoY29tYmluZWREZiRBY3Rpdml0eSA9PSAiTSIsIDEsIDApCmNvbWJpbmVkRGYkQWN0aXZpdHkgPC0gTlVMTApjb21iaW5lZERmJFBQX0Rldl8xX1R1cm5pbmcgPC0gTlVMTAoKY29tYmluZWREZiRTdGRfUFBfMl9TdHJhaWdodCA8LSBOVUxMCmNvbWJpbmVkRGYkU3RkX1BQXzJfVHVybmluZyA8LSBOVUxMCmNvbWJpbmVkRGYkU3RkX1BQXzNfU3RyYWlnaHQgPC0gTlVMTApjb21iaW5lZERmJFN0ZF9QUF8zX1R1cm5pbmcgPC0gTlVMTAoKIyBBY2NvcmRpbmcgdG8gTGluZWFyIG1vZGVsCmNvbWJpbmVkRGYkUFBfRGV2XzJfU3RyYWlnaHQgPC0gYWJzKGNvbWJpbmVkRGYkUFBfRGV2XzJfU3RyYWlnaHQpCmNvbWJpbmVkRGYkUFBfRGV2XzNfU3RyYWlnaHQgPC0gYWJzKGNvbWJpbmVkRGYkUFBfRGV2XzNfU3RyYWlnaHQpCmNvbWJpbmVkRGYkUFBfRGV2XzJfVHVybmluZyA8LSBhYnMoY29tYmluZWREZiRQUF9EZXZfMl9UdXJuaW5nKQpjb21iaW5lZERmJFBQX0Rldl8zX1R1cm5pbmcgPC0gYWJzKGNvbWJpbmVkRGYkUFBfRGV2XzNfVHVybmluZykKY29tYmluZWREZiRQUF9QcmlvciA8LSBhYnMoY29tYmluZWREZiRQUF9QcmlvcikgIyBOVUxMCgpjb21iaW5lZERmJENsYXNzIDwtIGlmZWxzZShjb21iaW5lZERmJFBQX0Rldl9Hcm91cCA9PSAxLCBULCBGKQpjb21iaW5lZERmJFBQX0Rldl9Hcm91cCA8LSBOVUxMCgpwcmludChuYW1lcyhjb21iaW5lZERmKSkKYGBgCgpgYGB7cn0KIyBsaWJyYXJ5KG1lZmEpCiMgY29tYmluZWREZiA8LSByZXAoY29tYmluZWREZiwgMTApIApgYGAKCmBgYHtyfQpzZXQuc2VlZCgzOSkKbl9mb2xkcyA8LSAzCnBhcmFtcyA8LSBwYXJhbSA8LSBsaXN0KG9iamVjdGl2ZSAgICAgICA9ICJiaW5hcnk6bG9naXN0aWMiLCAKICAgICAgICAgICAgICAgYm9vc3RlciAgICAgICAgICA9ICJnYnRyZWUiLAogICAgICAgICAgICAgICBldmFsX21ldHJpYyAgICAgID0gImF1YyIsCiAgICAgICAgICAgICAgIGV0YSAgICAgICAgICAgICAgPSAwLjEsCiAgICAgICAgICAgICAgIG1heF9kZXB0aCAgICAgICAgPSAxMCwKICAgICAgICAgICAgICAgYWxwaGEgICAgICAgICAgICA9IDEsCiAgICAgICAgICAgICAgIGxhbWJkYSAgICAgICAgICAgPSAwLAogICAgICAgICAgICAgICBnYW1tYSAgICAgICAgICAgID0gMC40NSwKICAgICAgICAgICAgICAgbWluX2NoaWxkX3dlaWdodCA9IDAuMywKICAgICAgICAgICAgICAgc3Vic2FtcGxlICAgICAgICA9IDEsCiAgICAgICAgICAgICAgIGNvbHNhbXBsZV9ieXRyZWUgPSAxKQogICAgICAgICAgIAojIFhHQm9vc3QgTW9kZWwgICAgICAgICAKeGdiX20gPC0geGdiLmN2KCAgIHBhcmFtcyAgICAgICAgICAgICAgID0gcGFyYW0sCiAgICAgICAgICAgICAgICAgIGRhdGEgPSBhcy5tYXRyaXgoY29tYmluZWREZiAlPiUgc2VsZWN0KC1DbGFzcykpICwKICAgICAgICAgICAgICAgICAgbGFiZWwgPSAgY29tYmluZWREZiRDbGFzcywKICAgICAgICAgICAgICAgICAgbnJvdW5kcyAgICAgICAgICAgICA9IDEwMCwKICAgICAgICAgICAgICAgICAgdmVyYm9zZSAgICAgICAgICAgICA9IEYsCiAgICAgICAgICAgICAgICAgIHByZWRpY3Rpb24gICAgICAgICAgPSBULAogICAgICAgICAgICAgICAgICBtYXhpbWl6ZSAgICAgICAgICAgID0gVCwgIyBDaGFuZ2UgdGhpcyB2YWx1ZSB0byBGIHdpbGwgaGVscCB0byBydW4gd2l0aCBtb3JlIGl0aW5lcmF0aW9uCiAgICAgICAgICAgICAgICAgIG5mb2xkICAgICAgICAgICAgICAgPSBuX2ZvbGRzLAogICAgICAgICAgICAgICAgICBtZXRyaWNzICAgICAgICAgICAgID0gYygiYXVjIiwgImVycm9yIiksCiAgICAgICAgICAgICAgICAgIGVhcmx5X3N0b3BwaW5nX3JvdW5kcyA9IDUwLAogICAgICAgICAgICAgICAgICBzdHJhdGlmaWVkICAgICAgICAgICAgPSBULAogICAgICAgICAgICAgICAgICBzY2FsZV9wb3Nfd2VpZ2h0ICAgICAgPSA3LzE0KQoKIyB4Z2JfbSRldmFsdWF0aW9uX2xvZ1t4Z2JfbSRiZXN0X2l0ZXJhdGlvbiwidGVzdF9hdWNfbWVhbiJdCnhnYl9tJGV2YWx1YXRpb25fbG9nW3hnYl9tJGJlc3RfaXRlcmF0aW9uLF0KCmBgYApgYGB7cn0KIyBQcmVkaWN0aW9uCmNvbWJpbmVkRGYkY2xzUHJlZCA8LSByb3VuZCh4Z2JfbSRwcmVkKQoKY29tcHV0ZVBlcmZvcm1hbmNlUmVzdWx0cyA8LSBmdW5jdGlvbihzZGF0KXsKICBzZGF0ID0gc2RhdFtjb21wbGV0ZS5jYXNlcyhzZGF0KSxdCiAgYWNjID0gc3VtKHNkYXRbLDFdID09IHNkYXRbLDJdKS9ucm93KHNkYXQpCiAgY29uZl9tYXQgPSB0YWJsZShzZGF0KQogIHNwZWNpZiA9IGNvbmZfbWF0WzEsMV0vc3VtKGNvbmZfbWF0WywxXSkKICBzZW5zaXYgPSBjb25mX21hdFsyLDJdL3N1bShjb25mX21hdFssMl0pCiAgcHJlY2kgPSAgY29uZl9tYXRbMiwyXS9zdW0oY29uZl9tYXRbMixdKQogIG5wdiA9ICAgIGNvbmZfbWF0WzEsMV0vc3VtKGNvbmZfbWF0WzEsXSkKICByZXR1cm4oYyhhY2Msc3BlY2lmLHNlbnNpdixwcmVjaSxucHYpKQp9CgojIEdldCBhdmVyYWdlIHBlcmZvcm1hbmNlCnBlcmZvcm1hbmNlIDwtIGNvbXB1dGVQZXJmb3JtYW5jZVJlc3VsdHMoY29tYmluZWREZiAlPiUgc2VsZWN0KENsYXNzLCBjbHNQcmVkKSkKYWNjIDwtIHBlcmZvcm1hbmNlWzFdCnByZWMgPC0gcGVyZm9ybWFuY2VbNF0KcmVjYWxsIDwtIHBlcmZvcm1hbmNlWzNdCnNwZWMgPC0gcGVyZm9ybWFuY2VbMl0KbnB2IDwtIHBlcmZvcm1hbmNlWzVdCmYxIDwtICgyICogcmVjYWxsICogcHJlYykgLyAocmVjYWxsICsgcHJlYykKYXVjIDwtIGFzLm51bWVyaWMoeGdiX20kZXZhbHVhdGlvbl9sb2dbeGdiX20kYmVzdF9pdGVyYXRpb24sICJ0ZXN0X2F1Y19tZWFuIl0pCgpwcmludChwYXN0ZSgiQWNjdXJhY3k9Iiwgcm91bmQoYWNjLCAyKSkpCnByaW50KHBhc3RlKCJQcmVjaXNpb249Iiwgcm91bmQocHJlYywgMikpKQpwcmludChwYXN0ZSgiUmVjYWxsPSIsIHJvdW5kKHJlY2FsbCwgMikpKQpwcmludChwYXN0ZSgiU3BlY2lmaWNpdHk9Iiwgcm91bmQoc3BlYywgMikpKQpwcmludChwYXN0ZSgiTlBWPSIsIHJvdW5kKG5wdiwgMikpKQpwcmludChwYXN0ZSgiRjE9Iiwgcm91bmQoZjEsIDIpKSkKcHJpbnQocGFzdGUoIkFVQz0iLCByb3VuZChhdWMsIDIpKSkKYGBgCgpgYGB7cn0KIyBJbXBvcnRhbmNlCmJzdCA8LSB4Z2Jvb3N0KCAgIHBhcmFtcyAgICAgICAgICAgICAgID0gcGFyYW0sCiAgICAgICAgICAgICAgICAgIGRhdGEgPSBhcy5tYXRyaXgoY29tYmluZWREZiAlPiUgc2VsZWN0KC1DbGFzcykpICwKICAgICAgICAgICAgICAgICAgbGFiZWwgPSAgY29tYmluZWREZiRDbGFzcywKICAgICAgICAgICAgICAgICAgbnJvdW5kcyAgICAgICAgICAgICA9IDEwMCwKICAgICAgICAgICAgICAgICAgdmVyYm9zZSAgICAgICAgICAgICA9IEYsCiAgICAgICAgICAgICAgICAgIHByZWRpY3Rpb24gICAgICAgICAgPSBULAogICAgICAgICAgICAgICAgICBtYXhpbWl6ZSAgICAgICAgICAgID0gVCwgIyBDaGFuZ2UgdGhpcyB2YWx1ZSB0byBGIHdpbGwgaGVscCB0byBydW4gd2l0aCBtb3JlIGl0aW5lcmF0aW9uCiAgICAgICAgICAgICAgICAgIG5mb2xkICAgICAgICAgICAgICAgPSBuX2ZvbGRzLAogICAgICAgICAgICAgICAgICBtZXRyaWNzICAgICAgICAgICAgID0gYygiYXVjIiwgImVycm9yIiksCiAgICAgICAgICAgICAgICAgIGVhcmx5X3N0b3BwaW5nX3JvdW5kcyA9IDUwLAogICAgICAgICAgICAgICAgICBzdHJhdGlmaWVkICAgICAgICAgICAgPSBULAogICAgICAgICAgICAgICAgICBzY2FsZV9wb3Nfd2VpZ2h0ICAgICAgPSAxKQppbXBvcnRhbmNlRGYgPC0geGdiLmltcG9ydGFuY2UoY29sbmFtZXMoY29tYmluZWREZiksIG1vZGVsID0gYnN0KQpwcmludChpbXBvcnRhbmNlRGYpCmBgYAoKYGBge3J9CmxpYnJhcnkocFJPQykKCmRmUk9DIDwtIHBST0M6OnJvYyhyZXNwb25zZSA9IGlmZWxzZShjb21iaW5lZERmJENsYXNzPT1ULCAxLCAwKSwKICAgICAgICAgICAgICAgcHJlZGljdG9yID0gcm91bmQoeGdiX20kcHJlZCksCiAgICAgICAgICAgICAgIGxldmVscz1jKDAsIDEpLCBkaXJlY3Rpb24gPSAiPCIpCgojIGl0ID0gd2hpY2gubWF4KHhnYl9tJGV2YWx1YXRpb25fbG9nJHRlc3RfYXVjX21lYW4pCiMgYmVzdC5pdGVyID0geGdiX20kZXZhbHVhdGlvbl9sb2ckaXRlcltpdF0KIyBiZXN0Lml0ZXIgCgpwbG90KHBST0M6OnJvYyhyZXNwb25zZSA9IGlmZWxzZShjb21iaW5lZERmJENsYXNzPT1ULCAxLCAwKSwKICAgICAgICAgICAgICAgcHJlZGljdG9yID0gcm91bmQoeGdiX20kcHJlZCksCiAgICAgICAgICAgICAgIGxldmVscz1jKDAsIDEpLCBkaXJlY3Rpb24gPSAiPCIpLCAKICAgICBsZWdhY3kuYXhlcyA9IFRSVUUsCiAgICAgbWFpbj0iUk9DIEN1cnZlIiwgCiAgICAgbHdkPTEuNSkgCmBgYAoKIyBJbXBvcnRhbnQgZmVhdHVyZXMKYGBge3J9CiMgRWxlbWluYXRlICM1IHdobyBoYXMgYW4gZXhjZXB0aW9uYWwgZGF0YSB0byBmaW5kIGEgYmV0dGVyIHRocmVzaG9sZApzdGRQUDMgPC0gc29ydChpbXBvcnRhbnRGZWF0dXJlc0RmJFN0ZF9QUF8zLCBkZWNyZWFzaW5nID0gVClbMjpsZW5ndGgoaW1wb3J0YW50RmVhdHVyZXNEZiRTdGRfUFBfMyldCnN0ZFBQM0FycmF5IDwtIG1hdHJpeChzdGRQUDMgLG5yb3cgPSAxLG5jb2wgPSBsZW5ndGgoc3RkUFAzKSkKICAKbWF4U3RkUFAzIDwtIHNvcnQoaW1wb3J0YW50RmVhdHVyZXNEZiRTdGRfUFBfMywgZGVjcmVhc2luZyA9IFQpWzJdClBQX0RFVl8zX1RIUkVTSE9MRCA8LSBvdHN1KHN0ZFBQM0FycmF5LCByYW5nZT1jKG1pbihzdGRQUDMpLCBtYXhTdGRQUDMpKSAjIEV4cGVjdGVkIFRocmVzaG9sZCA9IDAuMDg4CnByaW50KHBhc3RlMCgnVGhyZXNob2xkOiAnLCBQUF9ERVZfM19USFJFU0hPTEQpKQoKaW1wb3J0YW50RmVhdHVyZXNEZiRQUF9EZXZfM19Hcm91cCA8LSBpZmVsc2UoaW1wb3J0YW50RmVhdHVyZXNEZiRTdGRfUFBfMyA+IFBQX0RFVl8zX1RIUkVTSE9MRCwgMSwgMCkKd3JpdGUuY3N2KGltcG9ydGFudEZlYXR1cmVzRGYsICIuLi9vdXRwdXRzL2ltcG9ydGFudEZlYXR1cmVzLmNzdiIpCmBgYAoKIyBWZW5uIGRpYWdyYW0KYGBge3J9CmxpYnJhcnkoVmVubkRpYWdyYW0pCmxpYnJhcnkoUkNvbG9yQnJld2VyKQogCk1fTG93IDwtIHJvd25hbWVzKGltcG9ydGFudEZlYXR1cmVzRGZbaW1wb3J0YW50RmVhdHVyZXNEZiRQUF9EZXZfM19Hcm91cD09MCxdKQpNX0hpZ2ggPC0gcm93bmFtZXMoaW1wb3J0YW50RmVhdHVyZXNEZltpbXBvcnRhbnRGZWF0dXJlc0RmJFBQX0Rldl8zX0dyb3VwPT0xLF0pCgpGX0xvdyA8LSByb3duYW1lcyhpbXBvcnRhbnRGZWF0dXJlc0RmW2ltcG9ydGFudEZlYXR1cmVzRGYkUFBfRGV2X0dyb3VwPT0wLF0pCkZfSGlnaCA8LSByb3duYW1lcyhpbXBvcnRhbnRGZWF0dXJlc0RmW2ltcG9ydGFudEZlYXR1cmVzRGYkUFBfRGV2X0dyb3VwPT0xLF0pCgpqcGVnKCIuLi9wbG90cy92ZW5uL3Zlbm5fQWxsLnBuZyIsIHJlcz0xNTAsIHdpZHRoPTkwMCkKdmVubi5wbG90IDwtIHZlbm4uZGlhZ3JhbSgKICBsaXN0KE1fTG93LCBGX0xvdywgTV9IaWdoLCBGX0hpZ2gpLCBOVUxMLCAKICBmaWxsPWMoImJsdWUiLCAiYmx1ZSIsICJyZWQiLCAicmVkIiksIAogIGFscGhhPWMoMC41LDAuNSwwLjUsMC41KSwgCiAgcmVzb2x1dGlvbiA9IDE1MCwKICBjZXggPSAxLCAKICBjYXQuZm9udGZhY2U9MSwgCiAgY2F0ZWdvcnkubmFtZXM9YygiRHJpdmU9TVxuIFNEPUxvd1xuIiwgIkRyaXZlPUZcbiBBcm91c2FsPUxvd1xuIiwgIkRyaXZlPU1cbiBTRD1IaWdoXG4iLCAiRHJpdmU9RlxuIEFyb3VzYWw9SGlnaFxuIikKKQpncmlkLmRyYXcodmVubi5wbG90KQpkZXYub2ZmKCkKIyAKIyBqcGVnKCIuLi9wbG90cy92ZW5uL3Zlbm5fSGlnaC5wbmciLCByZXM9MTUwLCB3aWR0aD03MDApCiMgdmVubi5wbG90IDwtIHZlbm4uZGlhZ3JhbSgKIyAgIGxpc3QoTV9IaWdoLCBGX0hpZ2gpLCBOVUxMLCAKIyAgIGZpbGw9YygicGluayIsICJyZWQiKSwgCiMgICBhbHBoYT1jKDAuNSwwLjUpLCAKIyAgIHJlc29sdXRpb24gPSAxNTAsCiMgICBjZXggPSAxLCAKIyAgIGNhdC5mb250ZmFjZT0xLCAKIyAgIGNhdGVnb3J5Lm5hbWVzPWMoIkRyaXZlPU0iLCAiRHJpdmU9RiIpCiMgKQojIGdyaWQuZHJhdyh2ZW5uLnBsb3QpCiMgZGV2Lm9mZigpCmBgYAoKIyMjIFBsb3QgZmVhdHVyZSBpbXBvcnRhbmNlCmBgYHtyfQp5QXhpcyA8LSBsaXN0KAogIHRpdGxlID0gJ0ltcG9ydGFuY2UnLAogIHJhbmdlPWMoMC4wLCAxLjApCikKeEF4aXMgPC0gbGlzdCgKICB0aXRsZSA9ICcnCikKaW1wb3J0YW5jZURmJEZlYXR1cmVOYW1lIDwtIGxhcHBseShpbXBvcnRhbmNlRGYkRmVhdHVyZSwgZnVuY3Rpb24oeCkgewogIGlmZWxzZSh4PT0iU3RkX1BQXzMiLCAiU0Qgb2YgQXJvdXNhbFxuIGluIERyaXZlIE0iLCAKICAgICAgICAgaWZlbHNlKHg9PSJQUF9EZXZfMl9UdXJuaW5nIiwgIkFyb3VzYWwgaW4gRHJpdmUgQ1xuYXQgdHVybmluZyBzZWdtZW50cyIsIAogICAgICAgICAgICBpZmVsc2UoeD09IkFjdGl2aXR5X0MiLCAiUHJpb3Igc3RyZXNzb3JcbiBpcyBDb2duaXRpdmUiLCB4KSkpCn0pCgpmaWdfSW1wb3J0YW5jZSA8LSBwbG90X2x5KGltcG9ydGFuY2VEZiwgeCA9IH5GZWF0dXJlTmFtZSwgeSA9IH5HYWluLCB0eXBlID0gJ2JhcicsIG5hbWUgPSAnR2FpbicsIHdpZHRoPTYwMCkgJT4lCiAgYWRkX3RyYWNlKHkgPSB+Q292ZXIsIG5hbWUgPSAnQ292ZXInKSAlPiUgCiAgYWRkX3RyYWNlKHkgPSB+RnJlcXVlbmN5LCBuYW1lID0gJ0ZyZXF1ZW5jeScpICU+JSAKICBsYXlvdXQoeWF4aXMgPSB5QXhpcywgeGF4aXM9eEF4aXMsIGJhcm1vZGUgPSAnZ3JvdXAnLCB0aXRsZT0iRmVhdHVyZSBJbXBvcnRhbmNlIikgJT4lIAogIGNvbmZpZyguTGFzdC52YWx1ZSwgbWF0aGpheCA9ICdjZG4nKQoKaHRtbHRvb2xzOjp0YWdMaXN0KGZpZ19JbXBvcnRhbmNlKQpgYGAKCiMjIyBGZWF0dXJlCmBgYHtyfQpjbGFzc0NvbG9ycyA8LSBjKCJibHVlIiwgInJlZCIpCmZpZ1N0ZFZzRGV2IDwtIHBsb3RfbHkoZGF0YSA9IGltcG9ydGFudEZlYXR1cmVzRGYsIHggPSB+U3RkX1BQXzMsIHkgPSB+UFBfRGV2LCAKICAgICAgICAgICAgICAgICAgICAgICBjb2xvcj1+ZmFjdG9yKFBQX0Rldl9Hcm91cCksIGNvbG9ycz1jbGFzc0NvbG9ycywKICAgICAgICAgICAgICAgICAgICAgICBtYXJrZXI9bGlzdCh0ZXh0PSJYIikpICU+JQogIGxheW91dCh4YXhpcz1saXN0KHRpdGxlPSJTRCBvZiBBcm91c2FsIGluIE1vdG9yaWMgRHJpdmUgXG4gSHlwaGVuYXRlZCBsaW5lIGluZGljYXRlcyBkaXNjcmltaW5hdGl2ZSBib3VuZGFyeSIpLCB5YXhpcz1saXN0KHRpdGxlPSJBcm91c2FsIGF0IGNhdGFzdHJvcGhpYyBldmVudCIpLCBzaG93c2NhbGU9RikgJT4lCiAgbGF5b3V0KHNoYXBlcz1saXN0KAogICAgbGlzdCh4MD0wLjA4OCwgeDE9MC4wODgsIHkwPS0wLjEsIHkxPTAuMjUsIGxpbmU9bGlzdChkYXNoPSJkb3QiLCB3aWR0aD0xLCBjb2xvcj0iZ3JlZW4iKSkKICApKQpodG1sdG9vbHM6OnRhZ0xpc3QoZmlnU3RkVnNEZXYpCmBgYAoKYGBge3J9CmNsYXNzQ29sb3JzIDwtIGMoImJsdWUiLCAicmVkIikKZmlnU3RkVnNEZXYgPC0gcGxvdF9seShkYXRhID0gaW1wb3J0YW50RmVhdHVyZXNEZiwgeCA9IH5hYnMoUFBfRGV2XzJfVHVybmluZyksIHkgPSB+UFBfRGV2LCAKICAgICAgICAgICAgICAgICAgICAgICBjb2xvcj1+ZmFjdG9yKFBQX0Rldl9Hcm91cCksIGNvbG9ycz1jbGFzc0NvbG9ycywKICAgICAgICAgICAgICAgICAgICAgICBtYXJrZXI9bGlzdCh0ZXh0PSJYIikpICU+JQogIGxheW91dCh4YXhpcz1saXN0KHRpdGxlPSJTRCBvZiBBcm91c2FsIGluIE1vdG9yaWMgRHJpdmUiKSwgeWF4aXM9bGlzdCh0aXRsZT0iQXJvdXNhbCBhdCBjYXRhc3Ryb3BoaWMgZXZlbnQiKSkgJT4lCiAgbGF5b3V0KHNoYXBlcz1saXN0KAogICAgbGlzdCh4MD0wLjA4OCwgeDE9MC4wODgsIHkwPS0wLjEsIHkxPTAuMjUsIGxpbmU9bGlzdChkYXNoPSJkb3QiLCB3aWR0aD0xKSkKICApKQpodG1sdG9vbHM6OnRhZ0xpc3QoZmlnU3RkVnNEZXYpCmBgYAoKYGBge3J9CmNsYXNzQ29sb3JzIDwtIGMoImJsdWUiLCAicmVkIikKZmlnU3RkVnNEZXYgPC0gcGxvdF9seShkYXRhID0gaW1wb3J0YW50RmVhdHVyZXNEZiwgeSA9IH5hYnMoUFBfRGV2XzJfVHVybmluZyksIHggPSB+U3RkX1BQXzMsIAogICAgICAgICAgICAgICAgICAgICAgIGNvbG9yPX5mYWN0b3IoUFBfRGV2X0dyb3VwKSwgY29sb3JzPWNsYXNzQ29sb3JzLAogICAgICAgICAgICAgICAgICAgICAgIG1hcmtlcj1saXN0KHRleHQ9IlgiKSkgJT4lCiAgbGF5b3V0KHhheGlzPWxpc3QodGl0bGU9IlNEIG9mIEFyb3VzYWwgaW4gTW90b3JpYyBEcml2ZSIpLCB5YXhpcz1saXN0KHRpdGxlPSJBcm91c2FsIGF0IGNhdGFzdHJvcGhpYyBldmVudCIpLCBzaG93c2NhbGU9RikgJT4lCiAgbGF5b3V0KHNoYXBlcz1saXN0KAogICAgbGlzdCh4MD0wLjA4OCwgeDE9MC4wODgsIHkwPS0wLjEsIHkxPTAuMjUsIGxpbmU9bGlzdChkYXNoPSJkb3QiLCB3aWR0aD0xKSkKICApKQpodG1sdG9vbHM6OnRhZ0xpc3QoZmlnU3RkVnNEZXYpCmBgYAoKCg==